﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace TunerController
{
    public class Tuner
    {
        private const int TimeOutToRunApplication = 10000;
        private const string ProgramFilesVariable = "PROGRAMFILES(X86)";
        private const string BeholderDirectory = "\\BeholdTV\\";
        private const string TunerClassName = "TMain";
        private const string TunerWindowName = "BeholdTV";
        private const string TunerApplicationName = "beholdtv.exe";

        private static Tuner _instance;
        public static Tuner Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new Tuner();
                    SetDefaultValues();
                }
                return _instance;
            }
        }

        public string BeholderPath { get; set; }

        public void SetChannel(int numberChannel)
        {
            _args = "-m:tv -ch:" + numberChannel;
            PostTunerMessage(TunerConstants.WMBH_CHNLN, numberChannel);
        }

        private IntPtr _windowHandle = IntPtr.Zero;
        private IntPtr TunerWindow
        {
            get
            {
                if (_windowHandle != IntPtr.Zero)
                    return _windowHandle;
                if (InitTuner())
                    return _windowHandle;
                throw new Exception(TunerController.Tuner_TunerWindow_Could_not_find_window_with_tuner_application);
            }
        }
        private bool InitTuner()
        {
            _windowHandle = WinAPI.FindWindow(TunerClassName, TunerWindowName);
            if (_windowHandle != IntPtr.Zero)
                return true;
            StartTunerApplication();
            var current = DateTime.Now;
            do
            {
                _windowHandle = WinAPI.FindWindow(TunerClassName, TunerWindowName);
                Application.DoEvents();
            } while (_windowHandle == IntPtr.Zero && (DateTime.Now - current).TotalMilliseconds <= TimeOutToRunApplication);
            return _windowHandle != IntPtr.Zero;
        }
        private string _args;
        private bool _useArgs = false;
        private void StartTunerApplication()
        {
            _useArgs = false;
            var startInfo = new ProcessStartInfo { FileName = BeholderPath + TunerApplicationName };
            if (!string.IsNullOrWhiteSpace(_args))
            {
                startInfo.Arguments = _args;
                _args = null;
                _useArgs = true;
            }
            Process.Start(startInfo);
        }
        private static void SetDefaultValues()
        {
            _instance.BeholderPath = (Environment.GetEnvironmentVariable(ProgramFilesVariable) ?? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)) + BeholderDirectory;
        }
        private bool PostTunerMessage(int tunerParam, int tunerValue = 0)
        {
            var tw = TunerWindow;
            if (_useArgs)
            {
                _useArgs = false;
                return true;
            }
            GetTunerPosition();
            var res = WinAPI.PostMessage(tw, TunerConstants.WM_BHCMD, (IntPtr)tunerParam, (IntPtr)tunerValue);
            if (!res)
            {
                _windowHandle = IntPtr.Zero;
                tw = TunerWindow;
                if (_useArgs)
                {
                    _useArgs = false;
                    return true;
                }
                res = WinAPI.PostMessage(tw, TunerConstants.WM_BHCMD, (IntPtr)tunerParam, (IntPtr)tunerValue);
            }
            return res;
        }
        private int SendTunerMessage(int tunerParam, int tunerValue = 0)
        {
            return WinAPI.SendMessage((int)TunerWindow, TunerConstants.WM_BHCMD, tunerParam, tunerValue);
        }
        private void GetTunerPosition()
        {
            WinAPI.ShowWindow(TunerWindow, WinAPIConstants.WindowShowStyle.Show);
            WinAPI.ShowWindow(TunerWindow, WinAPIConstants.WindowShowStyle.ShowNormal);
            WinAPI.ShowWindow(TunerWindow, WinAPIConstants.WindowShowStyle.Restore);
            return;
            var placement = new WinAPIConstants.WINDOWPLACEMENT();
            placement.length = Marshal.SizeOf(placement);
            WinAPI.GetWindowPlacement(TunerWindow, ref placement);
        }

        //-inst:x Запустить копию (инстанс) приложения под профилем x (0-9). 
        //-m:tv Включить режим TV 
        //-m:fm Включить режим FM (для моделей с FM Radio) 
        //-m:cp
        //-m:cvbs Включить режим внешнего входа CVBS 
        //-m:sv
        //-m:yc Включить режим внешнего входа S-Video 
        //-m:yuv Включить режим внешнего входа YPbPr (для моделей с наличием компонентного входа) 
        //-m:rgb Включить режим внешнего входа RGB (для моделей с наличием компонентного входа) 
        //-m:dvbttv Включить режим DVB-T TV (для моделей с поддержкой DVB-T) 
        //-m:dvbtrd Включить режим DVB-T Radio (для моделей с поддержкой DVB-T) 
        //-fs Переключиться в полноэкранный режим 
        //-ch:xxx Переключить на xxx канал (нумерация с 1) 
        //-mute Выключить общий звук (не влияет на запись звука) 
        //-unmute Включить общий звук 
        //-lnmute Выключить звук линейного входа микшера (не применимо для режима записи) 
        //-vol:xxx Установить громкость xxx (0-255) 
        //-tr Запустить программу свернутую в трей (suspend to tray) 
        //-wu Активизировать программу из трея (wake up) 
        //-r:video Начать запись видео/аудио 
        //-r:audio Начать запись только аудио 
        //-r:stillxxx Начать запись скриншотов с интервалом в xxx секунд 
        //-d:xxx Длительность записи xxx минут 
        //-fn:"имя" Задать имя файла при захвате. Если имя не задано, применится таймштамп (обязательно в кавычках ) 
        //-nv Форсировать запись видео без просмотра (только с ключом -r:video) 
        //-ps:"имя.pst" Указать имя пресета для считывания настроек (обязательно в кавычках ) 
        //-exit После окончания записи выйти из программы 
        //-shut После окончания записи выйти из программы и выключить компьютер 


    }
}
